#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "stdlib.h"
#include "eeprom.h"
#include "key.h"
#include "timer.h"
#include "led.h"

#include "DataProcess.h"
#include "math.h"

#include "hx6203sys.h"
#include "PA_Driver.h"
#include "Seed_Driver.h"
#include "AMP_Driver.h"
#include "ExternComm.h"
#include "Protect.h"
#include "lcd.h"
#include "ui.h"

//整机状态结构体
struct HX6203_StateType HX6203 = {0};
struct Seed_StateType Seed = {0};
unsigned int HX6203_Protect = 0;

key_status_t key = {0};	//储存键值
uint8_t T2_Timer = 0;   //定时器2计数器
uint8_t TIME_FLAG=0;    //时标调度标志
uint8_t Refresh_Flag = 0;

uint8_t Power_Key = 0;  //电源键置位标志

int8_t ACT_Count = -1;
//功率手动调整计时 与设定功率相差无几时自加
uint8_t ACT_Timer = 0;
uint16_t Auto_Timer = 0;
//功率控制变量
uint16_t PowerValue = 0;
uint16_t PowerSetValue = 0;
//功率设置标志
uint8_t P_SetFlag = 0;
//功率调整完成标志
uint8_t P_Complete = 1;
//各路模块状态反馈
uint8_t NodeState[11] = {NORMAL};    //正常，绿色图标显示
//功率控制PID
enum SwitchType PID_LOCK = OFF;
//      上次误差        积分项
float P_LastDiff = 0;

//运行计时器
struct RUN_TIME
{
    uint16_t h;
    uint8_t m;
    uint8_t s;
}RunTime = {0};

const static eeprom_data_t eeprom_data_default = {
	.ampGateVoltage = AMP_GateVoltage,
	.fwdRFratio = 0,
	.pMapValue = P_MapValue,
	.pProtect = 2000
};

void HX6203_Init(void)
{
	HX6203.FwdRF=0;
	HX6203.RevRF=0;
	HX6203.AimRF=0;
	HX6203.FwdMap = 0;
	HX6203.LastAimRF=0;
	HX6203.STA=OFF;
	HX6203.LastSTA=OFF;
    
    HX6203.AMP_GateV_Flag = 1;
	
	HX6203.SetCountdown = -1;
	HX6203.ControlBit = 0;
    
    HX6203.PATempMax = 0;
    HX6203.PATempMin = 0;
    
	HX6203.Preamp[0].CommErr=0;
	HX6203.Preamp[1].CommErr=0;
    
    HX6203.AMP_STA = AMP_DISABLE;  //置1表示失能
	
	memcpy(&HX6203.EEPROMdata, &eeprom_data_default, sizeof(eeprom_data_t));
    
    BIT_SET(HX6203.StateBit, 0);
    BIT_SET(HX6203.StateBit, 1);
    
	Seed.Curr=0;
	Seed.Vbias=0;
	Seed.PD=0;
}

//整机运行状态数据清零
void HX6203_STA_Clear(void)
{
	uint8_t amp,pa;
	//清空变量状态
    HX6203.PATempMax = 0;
    HX6203.PATempMin = 0;
    
	HX6203.Preamp[0].Curr=0;
	HX6203.Preamp[0].Temp=0;
	HX6203.Preamp[0].Vbias=0;
	HX6203.Preamp[0].PD=0;
	HX6203.Preamp[1].Curr=0;
	HX6203.Preamp[1].Temp=0;
	HX6203.Preamp[1].Vbias=0;
	HX6203.Preamp[1].PD=0;
	for(amp=0;amp<AMP_NUM;amp++)
    {
        HX6203.AMP[amp].FwdRF=0;
        HX6203.AMP[amp].RevRF=0;
        HX6203.AMP[amp].AimRF=0;
        HX6203.AMP[amp].Vneg=0;
        HX6203.AMP[amp].CommErr=0;
        for(pa=0;pa<PA_NUM;pa++)
        {
            HX6203.AMP[amp].PA[pa].Curr=0;
            HX6203.AMP[amp].PA[pa].Temp=0;
            HX6203.AMP[amp].PA[pa].Vbias=0;
            HX6203.AMP[amp].PA[pa].PD=0;
            HX6203.AMP[amp].PA[pa].CommErr=0;
        }
    }
}

void EEPROMdataSet(void)
{
	if(HX6203.SetCountdown > -1)
	{
		if(!KEY3)
		{
			HX6203.SetCountdown--;
			if(HX6203.SetCountdown == 0)
			{
				HX6203.EEPROMdata.fwdRFratio = PowerSetValue / P_MapValue;	//计算功率比
				EEPROM_ContinuousWrite(EE_DATA_START, (uint8_t *)&HX6203.EEPROMdata, sizeof(eeprom_data_t));
			}
		}
		else if(!KEY4)	// 恢复默认参数配置
		{
			HX6203.SetCountdown--;
			if(HX6203.SetCountdown == 0)
			{
				memcpy(&HX6203.EEPROMdata, &eeprom_data_default, sizeof(eeprom_data_t));
				EEPROM_ContinuousWrite(EE_DATA_START, (uint8_t *)&HX6203.EEPROMdata, sizeof(eeprom_data_t));
				HX6203.AMP_GateV_Flag = 1;
			}
		}
		else
		{
			HX6203.SetCountdown = -1;
		}
	}
	if(fabs(HX6203.EEPROMdata.ampGateVoltage - AMP_GateVoltage) > 3)
	{
		EEPROM_ContinuousRead(EE_DATA_START, (uint8_t *)&HX6203.EEPROMdata, sizeof(eeprom_data_t));
	}
}

//功率启动
uint8_t HX6203RF_ON(void)
{
	uint8_t amp;
	//检查通信是否正常
	for(amp=0;amp<AMP_NUM;amp++)
    {
		if(HX6203.AMP[amp].CommErr)
        {
			if(HX6203.DebugMode)
                printf("Check Comm Faild! Amp=%d \n",amp);
			return 1;
		}
	}
	if(HX6203.Preamp[0].CommErr || HX6203.Preamp[1].CommErr)
    {
		if(HX6203.DebugMode)
            printf("Check Comm Faild! PrePA \n");
        return 1;
	}
    //获取每路刀片的写入返回值
	HX6203.AMP_STA = Set9AmpAImRF((uint16_t)(P_InitValue / 9));
	if(HX6203.AMP_STA)
    {
		if(HX6203.DebugMode)
            printf("RF ON Faild! Code=%x \n", HX6203.AMP_STA);
		return 1;
	}
	//设置前放PA
	delay_ms(10);
	setPAElementVoltage(0,-4.9);
	delay_ms(10);
	setPAElementVoltage(1,-4.9);
	//开启前放PA PD
	delay_ms(10);
	setPAElementPower(0,0x01);
	delay_ms(10);
	setPAElementPower(1,0x01);
	//开启种子源
	Seed.Vbias = 1.0f;	//赋予初值，提升开机速度
	Seed_SetVlotage(Seed.Vbias);
	delay_ms(1);
	GPIO_SetBits(GPIOA,GPIO_Pin_5);	//PA5置高
	Seed.PD=1;
    
    //重置设定功率和动作计数
    ACT_Count = -1;
    PowerValue = 0;
    
	//解锁PID
	PID_LOCK=ON;
	//重置PID变量
	P_LastDiff = 0;
    //设置最后状态
	HX6203.LastSTA=ON;
    //置位微波工作状态
    BIT_SET(HX6203.StateBit, 3);
	if(HX6203.DebugMode)
        printf("RF ON\n");
	return 0;
}

//功率关闭
uint8_t HX6203RF_OFF()
{
	//关闭种子源
	GPIO_ResetBits(GPIOA,GPIO_Pin_5);	//PA5置低
	Seed.PD=0;
	Seed.Vbias=0;
	Seed_SetVlotage(0);
	//锁定PID
	PID_LOCK=OFF;
	//刀片目标功率设置为0
	Set9AmpAImRF(0);
    HX6203.AMP_STA = AMP_DISABLE;  //置1表示失能
	//设置前放PA
	delay_ms(10);
	setPAElementVoltage(0,-4.9);
	delay_ms(10);
	setPAElementVoltage(1,-4.9);

	//关闭前放PA PD
	delay_ms(10);
	setPAElementPower(0,0);
	delay_ms(10);
	setPAElementPower(1,0);
    HX6203.Preamp[0].PD = 0;
    HX6203.Preamp[1].PD = 0;
    
	//重置PID变量
	P_LastDiff = 0;
    //清空设定功率
    ACT_Count = -1;
    PowerValue = 0;
    HX6203.AimRF = 0;
    HX6203.LastAimRF = 0;
	HX6203.LastSTA=OFF;
    //清空微波工作状态
    BIT_CLEAR(HX6203.StateBit, 3);
	if(HX6203.DebugMode)
        printf("RF OFF\n");
	return 0;
}
//设置刀片栅极电压
void AMP_GateVoltageSetting(void)
{
    if(HX6203.AMP_GateV_Flag)
    {
        for(uint8_t amp=0; amp<AMP_NUM; amp++)
        {
            if(HX6203.AMP[amp].CommErr)
                return;
        }
        if(Set9Amp_GateVoltage(AMP_GateVoltage) == 0)
            HX6203.AMP_GateV_Flag = 0;
    }
}

//HX6203自动运行控制
void AutoControl(void)
{
	uint8_t amp,pa,delay;
	const float P_Kp=0.00008f;
	const float P_Kd=0.00002f;
	const float P_Kp1=0.02f;
    const float P_Ki=0.0002f;
	float P_Diff=0, P_Diff2=0, PaVbiasAvg=0;
    
	if(Power_Key)
    {
        Power_Key = 0;
        if((HX6203.LastSTA==OFF) && (HX6203.STA==ON))
        {
//            while(KEY4==0);	//等待按键松开
            //系统开机
            if(HX6203RF_ON())
                HX6203.STA = OFF;	//若开启失败，回退到关机状态
        }
        if((HX6203.LastSTA==ON) && (HX6203.STA==OFF)){
//            while(KEY4==0);	//等待按键松开
            //系统关机
            HX6203RF_OFF();
        }
    }
	
		//通信异常，跳过PID
	for(amp=0;amp<AMP_NUM;amp++)
    {
        if(HX6203.AMP[amp].CommErr)
        {
            NodeState[amp] = ABNORMAL;
            return;
        }
    }
	
	//目标功率升高并且当前功率已达标，或是目标功率降低则进行PID控制
	if(((PowerValue > HX6203.LastAimRF) && P_Complete) || (PowerValue < HX6203.LastAimRF))
    {
        P_Complete = 0;
		//如果处于开机状态
		if(HX6203.STA == ON )
        {
            if(ACT_Count > 0)
            {
                if(PowerValue > HX6203.LastAimRF) HX6203.AimRF += P_Gradient;
                else HX6203.AimRF -= P_Gradient;
                ACT_Count--;
            }
            else if(ACT_Count == 0)
            {
                HX6203.AimRF = PowerValue;
                ACT_Count = -1;
            }
			delay = 5;
			while(delay--)
            {
                //向刀片设置目标功率，允许失败五次
                if(Set9AmpAImRF((uint16_t)(HX6203.AimRF/9))==0)	break;
                delay_ms(20);
            }
			if(delay == 0){
				//全部失败，自动关机
				if(HX6203.DebugMode)printf("Change Power Failed,Auto OFF\n");
				HX6203RF_OFF();
				return;
			}
		}
		
		if(HX6203.DebugMode)    printf("New Power=%f \n",HX6203.AimRF);
		HX6203.LastAimRF = HX6203.AimRF;
	}
  
    //计算正向功率、平均栅压
    HX6203.FwdRF=0;
    HX6203.RevRF=0;
    PaVbiasAvg=0;
    for(amp=0;amp<AMP_NUM;amp++)
    {
        HX6203.FwdRF += HX6203.AMP[amp].FwdRF;
        HX6203.RevRF += HX6203.AMP[amp].RevRF;
        for(pa=0;pa<PA_NUM;pa++)
            PaVbiasAvg += HX6203.AMP[amp].PA[pa].Vbias;
    }
	if(HX6203.EEPROMdata.fwdRFratio > 0)
		HX6203.FwdMap = HX6203.FwdRF / HX6203.EEPROMdata.fwdRFratio;	//正向功率映射，仅工业屏显示
	else
		HX6203.FwdMap = HX6203.FwdRF;
    if(PID_LOCK==ON)
    {
        PaVbiasAvg = PaVbiasAvg/27.0f;
        
        //计算本轮PID
        P_Diff = HX6203.AimRF - HX6203.FwdRF;   //计算偏差值1
        P_Diff2=PaVbiasAvg+4.4f;
        Seed.Vbias += P_Kp*P_Diff + P_Kd*(P_Diff-P_LastDiff);
        if(HX6203.FwdRF < 100.0f)           //提高功率启动速度
            Seed.Vbias += P_Ki*P_Diff;
        if(BiasBalanceFix)
            Seed.Vbias += P_Kp1*(P_Diff2);	//平衡修正项，可能造成少量误差无法回正
        P_LastDiff=P_Diff;
        if(Seed.Vbias>MaxSeedVbias)
            Seed.Vbias=MaxSeedVbias;
        //设置种子源推动偏压
        Seed_SetVlotage(Seed.Vbias);
    }
}

// 随机数测试
void Rand_Num()
{
    uint8_t i,j;
	
	HX6203.Preamp[0].Curr = (float)(rand()%20);
	HX6203.Preamp[0].Temp = (float)(rand()%100);
	HX6203.Preamp[1].Curr = (float)(rand()%20);
	HX6203.Preamp[1].Temp = (float)(rand()%100);
	
    for(i=0; i<9; i++)
    {
        for(j=0; j<3; j++)
        {
            HX6203.AMP[i].PA[j].Curr = (float)(rand()%120);
            HX6203.AMP[i].PA[j].Temp = (float)((rand()%90*120.0/90.0));
        }
		HX6203.AMP[i].FwdRF = (float)(rand()%800);
		HX6203.AMP[i].RevRF = (float)(rand()%120);
    }
}

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	Seed_Init();
	HX6203_Init();      //初值置零
    HX6203_STA_Clear();
	delay_init(168);
	
	TIM3_Int_Init(10000-1,8400-1);	//定时器时钟84M，分频系数8400，所以84M/8400=10Khz的计数频率，1s时标
	uart_init(115200);				//UART1调试串口，波特率为115200
	INTL_UART_Init(115200);		//UART6，内部RS485通讯串口
	PA485_UART_Init(115200);
	Extern485_Init(115200);
	
	printf("HX6203 %s %s\n", __DATE__, __TIME__);
	
	if(EEPROM_Configuration(&HX6203.EEPROMdata) == -1)	//初始化EEPROM
		printf("EEPROM not initialized!\n");
	else
		printf("\nEEPROM data\n"
				"ampGateVoltage: %.2f\n"
				"fwdRFratio: %.2f\n"
				"pMapValue: %d\n"
				"pProtect: %d\n",
				HX6203.EEPROMdata.ampGateVoltage,
				HX6203.EEPROMdata.fwdRFratio,
				HX6203.EEPROMdata.pMapValue,
				HX6203.EEPROMdata.pProtect);
	
	LED_Init();
	KEY_EXTIX_Init();
    KEY_EXTIX_Disable();
	
	LCD_Init();           //初始化LCD FSMC接口
    delay_ms(500);
    CurrADC_Init();
	HX6203_UI_Init();     //UI初始化
    	
    KEY_EXTIX_Enable();
    while(1)
	{
        Extern_UART_GetData();
		if(TIME_FLAG)		//时标挂起
		{
            TIME_FLAG = 0;
            Refresh_Flag = 1;
            LED0 = !LED0;
			KEY_EXTIX_Disable();
            
            AMP_GateVoltageSetting();

            //清空上次数据
            HX6203_STA_Clear(); //需要在流程最前面
			//获取种子源电流
			Get_Seed_Curr();
            //获取刀片状态
			Get9AmpSTA();
			//获取前放状态
			GetPrePASTA();
            
			//Rand_Num();
			//printf("%.2f\n%.2f\n", HX6203.EEPROMdata.fwdRFratio, HX6203.FwdMap);
			//printf("select value: %d\n", SELECT_VALUE(HX6203.EEPROMdata.pProtect, P_Protect));

            //自动功率控制
            AutoControl();
            //保护逻辑
			ProtectLogic();
			//出现告警或错误则将故障指示置位，否则清空
			if(HX6203_Protect)
			{
				BIT_SET(HX6203.StateBit, 4);
				if(ERROR_HAPPEN)	//需要关机处理
				{
					HX6203RF_OFF();	//系统关机
					BIT_SET(HX6203.StateBit, 13);   //当出现需要关机的错误时，故障标志置位
				}
			}
			else
			{
				BIT_CLEAR(HX6203.StateBit, 4);
			}
            
			//输出状态
			if(SeedDebugPrint)  printf("Seed I=%f A Vb=%f V PD=%d \n",Seed.Curr,Seed.Vbias,Seed.PD);
			 
            if(P_SetFlag && HX6203.STA == ON)   //开机后才可设置
            {
                P_SetFlag = 0;    //清空功率设置标志
                PID_LOCK = ON;    //开启功率自动调整
                if(PowerSetValue > P_UpLimit)  PowerSetValue = P_UpLimit;
                //计算设定功率差
                ACT_Count = fabs(PowerSetValue - HX6203.LastAimRF) / P_Gradient;
                PowerValue = PowerSetValue;
            }
			EEPROMdataSet();
            //使能外部按键
			if(HX6203.ControlBit == 0)
				KEY_EXTIX_Enable();
		}
        if(Refresh_Flag)
        {
            Refresh_Flag = 0;
            Refresh_UI();
        }
        if(HX6203.DebugMode && T2_Timer) 
        {
            if(!KEY1)       printf("KEY1 is Pressed\n");
            else if (!KEY2) printf("KEY2 is Pressed\n");
            else if (!KEY3) printf("KEY3 is Pressed\n");
            else if (!KEY4) printf("KEY4 is Pressed\n");
            delay_ms(200);
        }
	}
}

void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
    {
        if(T2_Timer < 255)  T2_Timer++;
        
        if(!KEY1)   //功率增加
        {
			key.val = 1;
			if(T2_Timer >= 50)
            {
                if((P_UpLimit-PowerSetValue) / 500)    PowerSetValue += 500;
                else PowerSetValue = P_UpLimit;
                TIM_SetAutoreload(TIM2, 2000);
            }
            Refresh_Flag = 1;
        }
        else if(!KEY2)  //功率降低
        {
			key.val = 2;
            if(T2_Timer >= 50)
            {
                if(PowerSetValue / 500)  PowerSetValue -= 500;
                else PowerSetValue = 0;
                TIM_SetAutoreload(TIM2, 2000);
            }
            Refresh_Flag = 1;
        }
        else if(!KEY3)  //输出功率，保持一定时间算为确认，避免微波干扰
        {
			key.val = 3;
			if(T2_Timer == 50)	//长按达1S后开启HX6203.EEPROMdata.fwdRFratio设定倒计时
				HX6203.SetCountdown = 4;
        }
        else if(!KEY4)  //开关机
        {
			key.val = 4;
			if((T2_Timer==50) && (HX6203.STA==OFF))	////长按达1S后开启HX6203.EEPROMdata回复默认设定倒计时
			{
				HX6203.SetCountdown = 4;
			}
        }
        else    //清空TIM2计数器，恢复定时器2的设置，失能定时器2
        {
			if(T2_Timer > 1 && T2_Timer < 50)	//判断短按
			{
				if(key.val == 1)
				{
					if((P_UpLimit-PowerSetValue) / 100)  PowerSetValue += 100;
					else PowerSetValue = P_UpLimit;
					Refresh_Flag = 1;
				}
				else if(key.val == 2)
				{
					if(PowerSetValue / 100)  PowerSetValue -= 100;
					else PowerSetValue = 0;
					Refresh_Flag = 1;
				}
				else if(key.val == 3)
				{
					if(T2_Timer > 10 && HX6203.STA == ON && PowerSetValue != PowerValue)
						P_SetFlag = 1;
				}
				else if(key.val == 4)
				{
					if((HX6203.STA==OFF) && (HX6203.LastSTA==OFF))	    
					{
						HX6203.STA = ON;
					}
					else if((HX6203.STA==ON) && (HX6203.LastSTA==ON))		
					{
						HX6203.STA = OFF;
					}
					Power_Key = 1;
				}
				key.val = 0;
			}
            T2_Timer = 0;
            TIM_SetAutoreload(TIM2, 200);
            TIM_Cmd(TIM2, DISABLE);
        }
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}

//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
	{
		TIME_FLAG = 1;	//恢复时间标志
        
        if(HX6203.STA == ON)    //开机后开始运行计时
        {
            RunTime.s++;
            if(RunTime.s > 59)
            {
                RunTime.s = 0;
                RunTime.m++;
                if(RunTime.m > 59)
                {
                    RunTime.m = 0;
                    RunTime.h++;
                }
            }
        }
        else
        {
            RunTime.s = 0;
            RunTime.m = 0;
            RunTime.h = 0;
        }
        
        Auto_Timer++;
        if(Auto_Timer > P_AutoTimeLimit)    //自动控制时间到时开启PID控制
        {
            Auto_Timer = 0;
            PID_LOCK = ON;
        }
        
        if((fabs(HX6203.FwdRF-HX6203.AimRF)) < 10)  //设定功率达标
        {
            ACT_Timer++;
            if(ACT_Timer > P_StableCount)
            {   
                ACT_Timer = 0;     //清空动作计时器
                P_Complete = 1;    //拉起功率准备标志位
                if(ACT_Count == -1) PID_LOCK = OFF;    //关闭PID
            }
        }
        else if((fabs(HX6203.FwdRF-HX6203.AimRF)) > P_Standard)    //设定功率未达标则开启PID
        {
            PID_LOCK = ON;
        }
        TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
	}
}
